package com.techyuan.algorithm.structure.map;

import java.util.*;

/**
 * 散列表：直接寻址表
 * Created by tianjuntao on 2016/12/12.
 */
@SuppressWarnings("unchecked")
public class DirectMap<V> implements Map<Integer, V> {
    private Object[] data;
    private int size = 0;

    public DirectMap(int capacity) {
        data = new Object[capacity];
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    public boolean containsKey(Object key) {
        return data[(Integer) key] != null;
    }

    public boolean containsValue(Object value) {
        if (value == null)
            return false;

        for (Object v : data) {
            if (v != null && value.equals(equals(v)))
                return true;
        }
        return false;
    }

    public V get(Object key) {
        Integer index = validKey(key);
        if (index == null) return null;

        return (V) data[index];
    }

    public V put(Integer key, V value) {
        Integer index = validKey(key);
        if (index == null) return null;
        V old = (V) data[index];
        if (old == null)
            size++;
        if (old != null && value == null)
            size--;
        data[index] = value;
        return old;
    }

    public V remove(Object key) {
        return put((Integer) key, null);
    }

    public void putAll(Map<? extends Integer, ? extends V> m) {
        for (Map.Entry<? extends Integer, ? extends V> entry : m.entrySet()) {
            put(entry.getKey(), entry.getValue());
        }
    }

    public void clear() {
        data = new Object[data.length];
        size = 0;
    }

    public Set<Integer> keySet() {
        HashSet<Integer> keys = new HashSet<Integer>();
        for (int i = 0; i < data.length; i++) {
            if (data[i] != null)
                keys.add(i);
        }
        return keys;
    }

    public Collection<V> values() {
        ArrayList<V> values = new ArrayList<V>();
        for (int i = 0; i < data.length; i++) {
            if (data[i] != null)
                values.add((V) data[i]);
        }
        return values;
    }

    public Set<Entry<Integer, V>> entrySet() {
        HashSet<Entry<Integer, V>> entrySet = new HashSet<Entry<Integer, V>>();
        for (int i = 0; i < data.length; i++) {
            if (data[i] != null)
                entrySet.add(new AbstractMap.SimpleEntry<Integer, V>(i, (V) data[i]));
        }
        return entrySet;
    }

    private Integer validKey(Object key) {
        Integer index = (Integer) key;
        if (index < 0 || index >= data.length)
            return null;
        return index;
    }
}
